/**
 * Augments canvas by assigning to `onObjectMove` and `onAfterRender`.
 * This kind of sucks because other code using those methods will stop functioning.
 * Need to fix it by replacing callbacks with pub/sub kind of subscription model.
 * (or maybe use existing fabric.util.fire/observe (if it won't be too slow))
 */
function initCenteringGuidelines(canvas) {

	var canvasWidth = canvas.getWidth(),
		canvasHeight = canvas.getHeight(),
		canvasWidthCenter = canvasWidth / 2,
		canvasHeightCenter = canvasHeight / 2,
		canvasWidthCenterMap = {},
		canvasHeightCenterMap = {},
		centerLineMargin = 4,
		centerLineColor = 'rgba(255,0,241,0.5)',
		centerLineWidth = 1,
		ctx = canvas.getSelectionContext(),
		viewportTransform;

	for (var i = canvasWidthCenter - centerLineMargin, len = canvasWidthCenter + centerLineMargin; i <= len; i++) {
		canvasWidthCenterMap[Math.round(i)] = true;
	}
	for (var i = canvasHeightCenter - centerLineMargin, len = canvasHeightCenter + centerLineMargin; i <= len; i++) {
		canvasHeightCenterMap[Math.round(i)] = true;
	}

	function showVerticalCenterLine() {
		showCenterLine(canvasWidthCenter + 0.5, 0, canvasWidthCenter + 0.5, canvasHeight);
	}

	function showHorizontalCenterLine() {
		showCenterLine(0, canvasHeightCenter + 0.5, canvasWidth, canvasHeightCenter + 0.5);
	}

	function showCenterLine(x1, y1, x2, y2) {
		ctx.save();
		ctx.strokeStyle = centerLineColor;
		ctx.lineWidth = centerLineWidth;
		ctx.beginPath();
		ctx.moveTo(x1 * viewportTransform[0], y1 * viewportTransform[3]);
		ctx.lineTo(x2 * viewportTransform[0], y2 * viewportTransform[3]);
		ctx.stroke();
		ctx.restore();
	}

	var afterRenderActions = [],
		isInVerticalCenter,
		isInHorizontalCenter;

	canvas.on('mouse:down', function() {
		viewportTransform = canvas.viewportTransform;
	});

	canvas.on('object:moving', function(e) {
		var object = e.target,
			objectCenter = object.getCenterPoint(),
			transform = canvas._currentTransform;

		if (!transform) return;

		isInVerticalCenter = Math.round(objectCenter.x) in canvasWidthCenterMap,
			isInHorizontalCenter = Math.round(objectCenter.y) in canvasHeightCenterMap;

		if (isInHorizontalCenter || isInVerticalCenter) {
			object.setPositionByOrigin(new fabric.Point((isInVerticalCenter ? canvasWidthCenter : objectCenter
				.x), (isInHorizontalCenter ? canvasHeightCenter : objectCenter.y)), 'center', 'center');
		}
	});

	canvas.on('before:render', function() {
		canvas.clearContext(canvas.contextTop);
	});

	canvas.on('after:render', function() {
		if (isInVerticalCenter) {
			showVerticalCenterLine();
		}
		if (isInHorizontalCenter) {
			showHorizontalCenterLine();
		}
	});

	canvas.on('mouse:up', function() {
		// clear these values, to stop drawing guidelines once mouse is up
		isInVerticalCenter = isInHorizontalCenter = null;
		canvas.renderAll();
	});
}

export default initCenteringGuidelines;